import { 
    PerspectiveCamera, 
    WebGLRenderer, 
    Scene, 
    Vector3, 
    Object3D,
    Vector2,
    Raycaster,
    MOUSE,
    Object3DEventMap,
    Mesh,
    MeshStandardMaterial,
    BufferGeometry,
} from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls';
import Stats from 'three/examples/jsm/libs/stats.module';
import { TEventManager, TEventManagerParameter } from "./tEventManager";

export class TEngine{
    private dom:HTMLElement
    private renderer: WebGLRenderer
    private scene:Scene
    private camera:PerspectiveCamera
    private controls:OrbitControls
    private transformControls: TransformControls
    private stats:Stats
    private eventManager: TEventManager

    constructor(dom:HTMLElement){
        this.dom = dom;
        // 初始化渲染器
        this.renderer = new WebGLRenderer({
            antialias: true
        });
        // 允许阴影
        this.renderer.shadowMap.enabled = true
        // 初始化场景
        this.scene = new Scene();
        // 初始化相机，透视相机
        this.camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 设置相机位置
        this.camera.position.set(240, 300, 300);
        // 设置相机朝向
        this.camera.lookAt(new Vector3(0, 0, 0));
        // 设置相机朝上方向
        this.camera.up = new Vector3(0, 1, 0)

        //设置页面大小
        this.renderer.setSize( window.innerWidth, window.innerHeight, true);

        // 控制器
        this.controls = new OrbitControls( this.camera, this.renderer.domElement );
        // 由控件所使用的鼠标操作的引用。
        this.controls.mouseButtons = {
            LEFT: null,
            MIDDLE: MOUSE.DOLLY,
            RIGHT: MOUSE.ROTATE,
        }

        // 初始变换控制器
        this.transformControls = new TransformControls( this.camera, this.renderer.domElement );
        let transing =false; // 区分触发的事件
        this.transformControls.addEventListener("mouseDown", (event)=>{
            transing = true
        })
        document.addEventListener("keyup",(event)=>{
            if(event.key == "e"){
                this.transformControls.mode = "scale"
            }
            if(event.key == "r"){
                this.transformControls.mode = "rotate"
            }
            if(event.key == "t"){
                this.transformControls.mode = "translate"
            }
        })

        this.eventManager = new TEventManager({
            scene: this.scene,
            dom: this.renderer.domElement,
            camera: this.camera
        })
        type M = Mesh<BufferGeometry, MeshStandardMaterial>
        let cacheObject3d: M | null = null
        // this.eventManager.addEventListener("mousemove",(event)=>{
        //     let scaleColor = 1.5
        //     if((event as any).intersectObjects.length){
        //         let object = (event as any).intersectObjects[0].object as M;
        //         if(object === cacheObject3d){
        //             return 
        //         }else if(cacheObject3d && object !== cacheObject3d){
        //             cacheObject3d.material.color.multiplyScalar(1 / scaleColor)
        //         }else if(object.material){
        //             object.material.color.multiplyScalar(scaleColor)
        //         }
        //         cacheObject3d = object
        //     }else{
        //         if(cacheObject3d){
        //             cacheObject3d.material.color.multiplyScalar(1 / scaleColor)
        //         }
        //         cacheObject3d = null
        //     }
        // })
        this.eventManager.addEventListener("click", (event)=>{
            if(transing) {
                transing = false
                return;
            }
            let intersectObjects = (event as any).intersectObjects
            if(intersectObjects.length>0){
                this.scene.add(this.transformControls)
                let object = intersectObjects[0].object as M;
                this.transformControls.attach(object)
            }else{
                this.transformControls.detach()
                this.scene.remove(this.transformControls)
            }
        })
        // 性能监视器
        this.stats = new Stats();
        const statsDom = this.stats.dom;
        statsDom.style.position = 'fixed';
        statsDom.style.left = '5px'
        statsDom.style.top = '0'

        // 添加场景到页面上
        this.dom.appendChild(this.renderer.domElement)
        this.dom.appendChild(statsDom)

        // 渲染数据
        this.animate();
    }
    addObject(...object:Object3D[]){
        object.forEach(element => {
            this.scene.add(element)
        });
    }
    animate() {
        requestAnimationFrame( this.animate.bind(this) );
        this.controls.update();
        this.stats.update();
        this.renderer.render( this.scene, this.camera );
    }
}